import React, {useCallback, useEffect, useRef, useState} from "react"
import {
    addProcurementReceiptItem,
    AddProcurementReceiptItemRequest, clearProcurementReceiptItems, convertProcurementReceiptOrderToMarketDeliveryOrder,
    deleteProcurementReceiptItem,
    deleteProcurementReceiptItemSub,
    downloadImportProcurementReceiptItemsTemplate,
    getProcurementReceiptDetail,
    importProcurementReceiptItemFromExcel,
    ProcurementReceiptDetail,
    ProcurementReceiptItem,
    updateProcurementReceiptItemAmount,
    updateProcurementReceiptItemSubAmount,
    updateProcurementReceiptNote,
    validateProcurementReceipt
} from "../../apis/ProcurementReceiptApi";
import {
    Button,
    Col,
    Descriptions,
    InputNumber,
    message,
    Popover,
    Row,
    Space,
    Table,
    theme,
    Typography,
    Upload
} from "antd";
import {OffsetDateTime} from "@js-joda/core";
import {
    convertAntdTableToExcel,
    convertAntdTableToExcelWithOptions,
    ExportedColumnProps,
} from "../../utils/AntdTableUtils";
import AuthorizationResource from "../../components/AuthorizationResource";
import {ClearOutlined, DeleteOutlined, EditOutlined, QuestionCircleOutlined, UploadOutlined} from "@ant-design/icons";
import DataPageLayout from "../../components/DataPageLayout";
import ArrayUtils from "@zxy-cn/array-utils";
import SingleInputPopover from "../../components/SingleInputPopover";
import dashboardPageStore from "../../store/DashboardPageStore";
import {observerDashboardPageWrapper} from "./ObserverDashboardPageWrapper";
import employeeAuthorizationStore from "../../store/EmployeeAuthorizationStore";
import EditOrderItemRow, {EditOrderItemGoodsData} from "../../components/EditOrderItemRow";
import {Link} from "react-router-dom";
import LoadableButton from "../../components/LoadableButton";
import {saveTo, saveWorkbookTo} from "../../utils/FileSaver";
import GoodsTable from "../../components/GoodsTable";
import {MarketOrderItem} from "../../apis/MarketOrderApi";
import {asyncConfirm} from "../../utils/AntdModalUtils";
import EditAmountAndUnitPopover from "../EditAmountAndUnitPopover";
import {DATE_WITH_TIME_FORMATER} from "../../utils/Date";
import {
    downloadImportProcurementItemsTemplate,
    findAllGoodsWithHistoryProcurementSupplier,
    importProcurementItemFromExcel
} from "../../apis/ProcurementApi";
import {useLiveQuery} from "dexie-react-hooks";
import {GoodsAmountAndUnitUseHistoryScope, myDatabase} from "../../database/MyDatabase";
import TableColumnSelectModal from "../TableColumnSelectModal";
import ConfirmPopover from "../ConfirmPopover";
import {useSubGoodsTableColumnConfiguration} from "../../utils/SubGoodsHooks";
import {async} from "q";
import {useNavigate} from "react-router";


export interface pageProps {
    id: number
}

const myPath = "procurements/receipts/{id}"

const ProcurementReceiptDetailPage: React.FC<pageProps> = ({id}) => {
    const [loading, setLoading] = useState(false)
    const [data, setData] = useState<ProcurementReceiptDetail>()
    const query = useCallback(() => {
        setLoading(true)
        getProcurementReceiptDetail(id).then(response => {
            dashboardPageStore.setTitle(myPath.replace("{id}", id.toString()), response.data.supplier.name + "采购入库单")
            setData(response.data)
        }).finally(() => {
            setLoading(false)
        })
    }, [id,])

    useEffect(() => {
        query()
    }, [query]);

    let token = theme.useToken();
    let columnsRef = useRef<ExportedColumnProps<ProcurementReceiptItem>[]>();

    let amountAndUnitHistories = useLiveQuery(() => {
        return myDatabase.goodsAmountAndUnitUseHistory.where({
            scope: GoodsAmountAndUnitUseHistoryScope.PROCUREMENT,
            resourceId: id,
        }).toArray()
    }, [id]);

    const [importing, setImporting] = useState(false)
    const [messageApi, contextHolder] = message.useMessage();

    const [openExportColumnSelectModal, setOpenExportColumnSelectModal] = useState(false)
    let configSubGoodsColumns = useSubGoodsTableColumnConfiguration<ProcurementReceiptItem>();

    let navigate = useNavigate();
    return (
        <>
            {contextHolder}
            <div style={{display: "flex", flexDirection: "column"}}>
                {!loading ? <Descriptions title={"订单明细"}>
                    <Descriptions.Item label={"供货商"}>{data?.supplier?.name}</Descriptions.Item>
                    {!!data?.createdDateTime && <Descriptions.Item
                        label={"开单时间"}>{data?.createdDateTime.format(DATE_WITH_TIME_FORMATER)}</Descriptions.Item>}
                    {!!data?.validatedDateTime ? <Descriptions.Item
                        label={"验收时间"}>{data.validatedDateTime.format(DATE_WITH_TIME_FORMATER)}</Descriptions.Item> : undefined}
                </Descriptions> : null}
                <Row gutter={8} style={{margin: "12px 0"}}>
                    <Col>
                        {!data?.validatedDateTime && employeeAuthorizationStore.hasAuthority("采购_入库_修改") ?
                            <Space size={4}>
                                <Upload fileList={[]}
                                        accept={"application/vnd.ms-excel,application/vnd.openxmlformats-officedocument.spreadsheetml.sheet"}
                                        maxCount={1}
                                        beforeUpload={async file => {
                                            setImporting(true)
                                            try {
                                                let response = await importProcurementReceiptItemFromExcel(id, file)
                                                if (response.data) {
                                                    query();
                                                    messageApi.success(`成功导入${response.data}个货品`);
                                                } else {
                                                    messageApi.error(`无货品被导入，请检查格式是否正确`);
                                                }
                                            } finally {
                                                setImporting(false)
                                            }
                                            return false
                                        }}>
                                    <Button icon={<UploadOutlined/>}
                                            loading={importing}>导入</Button>
                                </Upload>
                                <Popover title={"导入货品"} content={
                                    <Typography>
                                        <Typography.Paragraph>
                                            按照约定的格式上传excel文件。
                                            <Typography.Link onClick={() => {
                                                downloadImportProcurementReceiptItemsTemplate().then(res => res.data)
                                                    .then(blob => {
                                                        saveTo(blob, "导入采购入库单模板.xlsx")
                                                    })

                                            }}>下载模板</Typography.Link>
                                        </Typography.Paragraph>
                                        <Typography.Paragraph>
                                            <ul>
                                                <li>默认使用以前的采购价或者进价，如果都不存在则采购价为0</li>
                                                <li>相同的条码，和子商品编号会被忽略</li>
                                                <li>必填的属性未填会被忽略</li>
                                            </ul>
                                        </Typography.Paragraph>
                                    </Typography>
                                }><QuestionCircleOutlined/></Popover>
                            </Space> : undefined}
                    </Col>
                    <Col>
                        <LoadableButton onClick={async event => {
                            setOpenExportColumnSelectModal(true)
                        }}>导出</LoadableButton>
                    </Col>
                    <Col>
                        {employeeAuthorizationStore.hasAuthority("采购_入库_修改") && !data?.validatedDateTime &&
                            <ConfirmPopover onConfirm={async () => {
                                await clearProcurementReceiptItems(id)
                                setData({
                                    ...data!!,
                                    items: []
                                })
                            }} description={"是否要清空此采购入库单"}>
                                <Button icon={<ClearOutlined/>} danger>清空</Button>
                            </ConfirmPopover>}
                    </Col>
                    <div style={{flexGrow: 1}}/>
                    <TableColumnSelectModal cacheKey={"procurementReceipt"}
                                            availableColumns={["条码", "名称", "子商品编号", "子商品名称", "数量与单位", "数量", "验收数量", "单位", "零售价", "备注"]}
                                            open={openExportColumnSelectModal} onConfirm={async fields => {
                        let columns = Array.from(columnsRef.current!!);
                        ArrayUtils.insertAfter(columns, value => value.dataIndex === "amountInOrder", {
                            dataIndex: "amountWithoutUnit",
                            title: "数量",
                            render: (_, record) => {
                                return record.amountInOrder
                            },
                        },)
                        ArrayUtils.insertAfter(columns, value => value.dataIndex === "amountWithoutUnit", {
                            dataIndex: "unit",
                            title: "单位",
                            render: (_, record) => {
                                return record.unit?.name
                            },
                        },)
                        let workbook = await convertAntdTableToExcelWithOptions(columns, data?.items ?? [], {
                            selectedColumns: fields, postHandler: worksheet => {
                                if (data?.note) {
                                    let nextRow = worksheet.getRow(worksheet.lastRow!!.number + 1);
                                    nextRow.getCell(1).value = "备注"
                                    nextRow.getCell(2).value = data.note
                                    worksheet.mergeCells(nextRow.number, 2, nextRow.number, worksheet.lastColumn!.number)
                                }

                            }
                        });
                        await saveWorkbookTo(workbook, `${data?.supplier?.name}采购入库单-${data?.createdDateTime ?? data!.createdDateTime.format(DATE_WITH_TIME_FORMATER)}`)
                        setOpenExportColumnSelectModal(false)
                    }} onCancel={_ => setOpenExportColumnSelectModal(false)}/>

                    <Link to={`/procurements/${data?.procurementId}`}>
                        <Button type={"link"}>查看采购单</Button>
                    </Link>

                    <SingleInputPopover title={"输入卖场订单编号"} onConfirm={async value => {
                        try {
                            let response = await convertProcurementReceiptOrderToMarketDeliveryOrder(id, value);
                            navigate(`/markets/deliveryOrders/${response.data}`)
                        } catch (e:any) {
                            await messageApi.error(e.data.detail??"未知错误")
                            throw e
                        }
                    }} fieldName={"订单编号"}>
                        <Button>生成卖场送货单</Button>
                    </SingleInputPopover>
                    {employeeAuthorizationStore.hasAuthority("采购_入库_验收") && !data?.validatedDateTime &&
                        <Col>
                            <LoadableButton type={"primary"} onClick={async () => {
                                await asyncConfirm({
                                    title: "确认验收",
                                    content: "确认验收后，入库单将无法再修改，库存将会被更新？",
                                    onOk: async () => {
                                        await validateProcurementReceipt(id)
                                        setData({
                                            ...data!!,
                                            validatedDateTime: OffsetDateTime.now(),
                                        })
                                    }
                                })
                            }}>
                                验收
                            </LoadableButton>
                        </Col>}
                    {employeeAuthorizationStore.hasAuthority("采购_入库_验收") && !data?.validatedDateTime &&
                        <Col>
                            <LoadableButton type={"primary"} onClick={async () => {
                                await asyncConfirm({
                                    title: "确认验收",
                                    content: "未被验收的货品将默认全部验收，确认验收后，入库单将无法再修改，库存将会被更新？",
                                    onOk: async () => {
                                        await validateProcurementReceipt(id, true)
                                        setData({
                                            ...data!!,
                                            items: data!!.items.map(it => ({
                                                ...it,
                                                practicalAmount: it.practicalAmount ?? it.amountInOrder
                                            })),
                                            validatedDateTime: OffsetDateTime.now(),
                                        })
                                    }
                                })
                            }}>
                                验收剩余货品
                            </LoadableButton>
                        </Col>}
                </Row>

                {data && employeeAuthorizationStore.hasAuthority("采购_入库_修改") && !data.validatedDateTime &&
                    <EditOrderItemRow<EditOrderItemGoodsData>
                        request={{}}
                        withAmount
                        fetchGoods={async () => {
                            let response = await findAllGoodsWithHistoryProcurementSupplier(data!!.supplier.id);
                            return response.data.flatMap(it => {
                                if (it.subGoodsList && !!it.subGoodsList.length) {
                                    return it.subGoodsList.map(subGoods => ({
                                        ...it,
                                        units: [],
                                        price: it.price,
                                        rememberedPrice: it.rememberedPurchasePrice,
                                        subGoods: subGoods
                                    }))
                                } else {
                                    return [{...it, rememberedPrice: it.rememberedPurchasePrice}]
                                }
                            })
                        }}
                        optionRender={it => {
                            return <Space>
                                <span>{it.subGoods ? `${it.barcode}|${it.subGoods.number}` : it.barcode}</span>
                                <span>{it.subGoods ? it.subGoods.name + `（${it.name}）` : it.name}</span>
                            </Space>
                                ;
                        }}
                        onFinish={async values => {
                            let existed = amountAndUnitHistories?.find(it => it.goodsId === values.goodsId);
                            if (existed) {
                                myDatabase.goodsAmountAndUnitUseHistory.delete(existed.id!!)
                            }
                            myDatabase.goodsAmountAndUnitUseHistory.add({
                                scope: GoodsAmountAndUnitUseHistoryScope.PROCUREMENT,
                                resourceId: id,
                                amount: values.amount,
                                unitId: values.unitId,
                                goodsId: values.goodsId,
                            })
                            return addProcurementReceiptItem(id, values).then(() => {
                                query();
                            })
                        }}
                        existedGoodsKeys={data?.items?.map(it => ({
                            goodsId: it.id,
                            subGoodsId: it.subGoods?.id,
                        })) ?? []}
                    ></EditOrderItemRow>}
                <DataPageLayout leftActions={<>
                </>}>

                    <GoodsTable<ProcurementReceiptItem> loading={loading}
                                                        summary={() => {
                                                            let index = -1
                                                            return <>
                                                                <Table.Summary.Row>
                                                                    <Table.Summary.Cell
                                                                        index={++index}>总零售金额</Table.Summary.Cell>
                                                                    <Table.Summary.Cell
                                                                        index={++index}>{ArrayUtils.sum(data?.items?.map(it => it.amountInOrder * it.price) ?? []).toFixed(2)}</Table.Summary.Cell>
                                                                    <Table.Summary.Cell index={2}>总采购价</Table.Summary.Cell>
                                                                    <Table.Summary.Cell
                                                                        index={3}>{ArrayUtils.sum(data?.items?.map(it => it.amountInOrder * ((it.units.find(unit => unit.id === it.unit?.id)?.basicMultiple) || 1) * it.purchasePrice) ?? []).toFixed(2)}</Table.Summary.Cell>
                                                                    <>
                                                                        <Table.Summary.Cell
                                                                            index={++index}>备注</Table.Summary.Cell>
                                                                        <Table.Summary.Cell index={(() => {
                                                                            index += 5;
                                                                            return index
                                                                        })()} colSpan={5}>
                                                                            <Space>
                                                                                <Typography.Text>{data?.note ? data.note : "无"}</Typography.Text>
                                                                                {!!data && <SingleInputPopover required
                                                                                                               initialValue={data.note}
                                                                                                               title={"修改备注"}

                                                                                                               onConfirm={async value => {
                                                                                                                   await updateProcurementReceiptNote(id, value)
                                                                                                                   setData({
                                                                                                                       ...data!,
                                                                                                                       note: value,
                                                                                                                   })
                                                                                                               }}
                                                                                                               fieldName={"备注"}>

                                                                                    <Button icon={<EditOutlined/>}
                                                                                            type={"link"}/>
                                                                                </SingleInputPopover>}
                                                                            </Space>
                                                                        </Table.Summary.Cell>
                                                                    </>
                                                                </Table.Summary.Row>
                                                            </>
                                                        }}
                                                        data={data?.items ?? []}
                                                        size={"small"}
                                                        customColumns={columns => {
                                                            configSubGoodsColumns(columns)
                                                            ArrayUtils.insertAfter(columns, value => value.dataIndex === "name", {
                                                                dataIndex: "amountInOrder",
                                                                title: "数量",
                                                                render: (value, record) => {
                                                                    return <div>{value}{record.unit?.name}</div>
                                                                },
                                                                generateExcelValue: (value, record) => {
                                                                    return `${value}${record.unit?.name}`
                                                                }
                                                            },)
                                                            ArrayUtils.insertAfter(columns, value => value.title === "数量", {
                                                                dataIndex: "practicalAmount",
                                                                title: "验收数量"
                                                            })
                                                            ArrayUtils.insertAfter(columns, value => value.dataIndex === "price", {
                                                                dataIndex: "purchasePrice",
                                                                title: "采购价",
                                                            },)
                                                            columns.push({
                                                                dataIndex: "note",
                                                                title: "备注",
                                                            })
                                                            columns.push({
                                                                ignoreInExcel: true,
                                                                title: "操作",
                                                                render: (_, item, index) => {
                                                                    return <>
                                                                        {(employeeAuthorizationStore.hasAuthority(
                                                                                "采购_入库_修改"
                                                                            )) && !data?.validatedDateTime &&
                                                                            <EditAmountAndUnitPopover units={item.units}
                                                                                                      initialData={{
                                                                                                          amount: item.amountInOrder,
                                                                                                          unitId: item.unit?.id
                                                                                                      }}

                                                                                                      onConfirm={async value => {
                                                                                                          if (item.subGoods) {
                                                                                                              await updateProcurementReceiptItemSubAmount(id, item.id, item.subGoods.id, value)
                                                                                                          } else {
                                                                                                              await updateProcurementReceiptItemAmount(id, item.id, value)
                                                                                                          }
                                                                                                          await updateProcurementReceiptItemAmount(id, item.id, value)
                                                                                                          let items = Array.from(data?.items ?? []);
                                                                                                          let item1 = items[index];
                                                                                                          item1.amountInOrder = value.amount
                                                                                                          item1.unit = item.units.find(it => it.id === value.unitId)
                                                                                                          setData({
                                                                                                              ...data!,
                                                                                                              items
                                                                                                          })
                                                                                                      }}
                                                                            >
                                                                                <Button type={"link"}>修改数量</Button>
                                                                            </EditAmountAndUnitPopover>}

                                                                        <AuthorizationResource
                                                                            authorities={["采购_入库_修改"]}>
                                                                            <Button type={"link"}
                                                                                    danger
                                                                                    onClick={async (event) => {
                                                                                        event.stopPropagation()
                                                                                        if (item.subGoods) {
                                                                                            await deleteProcurementReceiptItemSub(id, item.id, item.subGoods.id)
                                                                                        } else {
                                                                                            await deleteProcurementReceiptItem(id, item.id)
                                                                                        }
                                                                                        let items = Array.from(data!.items);
                                                                                        ArrayUtils.remove(items, item)
                                                                                        setData({
                                                                                            ...data!,
                                                                                            items
                                                                                        })
                                                                                    }}>
                                                                                <DeleteOutlined/>
                                                                                删除
                                                                            </Button>
                                                                        </AuthorizationResource>
                                                                    </>
                                                                }
                                                            },);
                                                            columnsRef.current = columns;
                                                            return columns;
                                                        }}
                                                        rowKey={(record, _) => {
                                                            return record.id.toString() + (record.subGoods?.id ?? "")
                                                        }}>
                    </GoodsTable>|
                </DataPageLayout></div>

        </>
    )
}

export default observerDashboardPageWrapper(ProcurementReceiptDetailPage, myPath, "采购入库单详情")

